package com.dissertation.config.auth;


import com.dissertation.model.auth.Permission;
import com.dissertation.model.auth.Role;
import com.dissertation.model.auth.User;
import com.dissertation.respository.UserRepository;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserRepository userRepository;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals ) {
        User u = (User) principals.getPrimaryPrincipal();
        Optional<User> user = Optional.ofNullable( u );

        Set<Role> userRoles = user.map( User::getRole )
                .orElseThrow( () -> new RuntimeException( "对不起，用户没有角色" ) );

        Set<String> userString = userRoles.stream().map( Role::getName )
                .collect( Collectors.toSet() );

        Set<String> userPermissions = new HashSet<>();

        userRoles.forEach( role -> userPermissions.addAll( role.getPermissions().
                stream()
                .map( Permission::getName )
                .collect( Collectors.toSet()) )
        );

        System.out.println( "#######获取角色：" + userRoles );
        System.out.println( "#######获取权限：" + userPermissions );

        //为当前用户设置角色和权限
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.addStringPermissions( userPermissions );
        authorizationInfo.addRoles( userString );
        return authorizationInfo;
    }

    /**
     * 验证当前登录的Subject
     * LoginController.login()方法中执行Subject.login()时 执行此方法
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token ) throws AuthenticationException {
        System.out.println( "###【开始认证[SessionId]】" + SecurityUtils.getSubject().getSession().getId() );
        UsernamePasswordToken passwordToken = (UsernamePasswordToken) token;
        Optional<User> userOptional = userRepository.findByUniqueName( passwordToken.getUsername() );
        User user = userOptional.orElseThrow( () -> new RuntimeException( "对不起，用户不存在" ) );
        return new SimpleAuthenticationInfo(
                user, //用户名
                user.getPassword(), //密码
                getName()  //realm name
        );
    }
}
